package cs437;
import java.util.Vector;
import com.trolltech.qt.QPair;
import com.trolltech.qt.core.*;
import com.trolltech.qt.gui.*;


public class Talent extends QGraphicsItem
{
	private String name;
	private int ranks;
	public String currentRank = "";
	public String nextRank = "";
	
	//Position Knowledge
	private int tier;
	private int position;
	
	//Active Knowledge
	private boolean active;
	private boolean locked;
	private int ranksAchieved;


	//Dependency Properties
	boolean hasDependency;
	boolean isDependent;	

	public Vector<QPair<Integer, Integer>> child;
	public QPair<Integer, Integer> parent;
	
	public Vector<String> rankInfo;
		
	//Display Details
	private QPixmap icon;
	private static int width = 40;
	private static int height = 40;

	//Signals
	public Signal1<Integer> activated = new Signal1<Integer>(); 
	public Signal1<Integer> deActivated = new Signal1<Integer>(); 
	public Signal1<Integer> maxed = new Signal1<Integer>(); 
	public Signal1<Integer> unMaxed = new Signal1<Integer>();
	public Signal3<Integer, Integer, Integer> pointSpent = new Signal3<Integer, Integer, Integer>();
	public Signal1<Talent> hovering = new Signal1<Talent>();
	
	//
	private RankWindow rw;
	
	/**************************
	 * 
	 * @param name
	 * @param ranks
	 * @param tier
	 * @param pos
	 * @param iconFile
	 * 
	 * @Description Constructs a talent with the given elements
	 ***************************/
    public Talent(String name, int ranks, int tier, int pos, String iconFile)
    {
    	this.name = name;
    	this.ranks = ranks;
    	this.tier = tier;
    	this.position = pos;
    	if (tier == 1) this.active = true;
    	else this.active = false;
    	this.locked = false;
    	this.ranksAchieved = 0;
    	child = new Vector<QPair<Integer,Integer>>();
    	this.icon = new QPixmap(iconFile); 
    	setAcceptsHoverEvents(true);
    	rankInfo = new Vector<String>();
    	rw = new RankWindow(name, this, pos);
    	rw.setVisible(false);
    	if (pos < 3)
    		rw.setPos(new QPointF(width+5, 0));
    	else 
    		rw.setPos(new QPointF(-120, 0));
    	
    	
    }
    public Talent(QWidget parent){
       //
    }
    /****************************************************
     * The following data is required to display the GraphicsItem
     *****************************************************/
    
    /*****************************************************
     * boundingRect sets up boundaries 
     *****************************************************/
    private QRectF boundingRect = new QRectF(0, 0, width, height);
	public QRectF boundingRect()
	{
		return boundingRect;
	}
	
	/***************************************************** 
	 * Shape: This function is an interface function QT requires of QGraphicItems
	 * Shape defines the shape of the object; Used in collision detection
	 * Ours has a defined height and width
	 *****************************************************/
	QPainterPath shape = new QPainterPath();
	{
		shape.addRoundRect(0, 0, width+1, height+1, 20);
	}	
	public QPainterPath shape() {
		return shape;
	}
	
	/*****************************************************
	 * @Description Paint: This function is an interface function QT requires of QGraphicItems
	 * @Purpose: Draws the GraphicsItem on screen using a combination of Brushes, Pens and Pixmaps. 
	 *****************************************************/
	public void paint(QPainter painter, QStyleOptionGraphicsItem option,
	QWidget widget)
	{
		//Brush & Light Blue color for BG		
		QColor black = QColor.black;
		black.setAlphaF(0.35);
		QBrush brush = new QBrush(black);
		
		if (!scene().collidingItems(this).isEmpty())
		{
			brush.setColor(QColor.red);
		}
		
		/****************************************************
		 * Drawing the Child Connection
		 * If the talent has a child, it draws an arrow from itself to the child
		 * This is done by subtracting the talent's tier from the child's tier # then multiplying that by the height.
		 * The child is always in the same x-position
		 * S
		 *****************************************************/
		for(int i = 0; i < child.size(); i++)
		{
			drawChild(child.get(i), painter);
		}
		
		//painter.fillPath(shape, brush);
		//painter.drawPath(shape);		

		// Draw the Icon associated with this talent
		painter.drawPixmap(1, 1, icon);		
		
		/***************************************************** 
		 * Set the pen color.
		 * Case 1: Talent is maxed. Color = Gold
		 * Case 2: Talent is active and not full. Color = green
		 * Case 3: Talent is inactive. Color = Grey
		*****************************************************/
				
		if (ranks == ranksAchieved) painter.setPen(QColor.yellow);
		else if (this.active) painter.setPen(QColor.green);	
		else {
			painter.setPen(QColor.darkGray);
			painter.fillPath(shape, brush);
		}
		
		//Draw the Box that borders the ranks/ranksAchieved
		QRectF box = new QRectF(width-10, height-10, 20, 15);		
		QPainterPath pp = new QPainterPath();		
		pp.addRoundRect(box, 25);
		painter.fillPath(pp, new QBrush(QColor.fromRgb(0, 0, 0)));
		painter.drawPath(pp);
		
		//Draw the rankAchieved/ranks
		painter.drawText(box, 0, String.valueOf(" " + this.ranksAchieved) + "/" + String.valueOf(this.ranks), box);	
	}
	
	public void addRank(String info)
	{
		rankInfo.add(info);
	}

	/*
	 * Activating and DeActivating
	 * Locking and Unlocking
	 */
	
	/**********************
	 * @Description Activates Talent for use
	 **********************/
	public void activate()
	{
		active = true;
		activated.emit(1);
	}
	/**********************
	 * @Description Deactivates Talent
	 **********************/
	public void deActivate()
	{
		active = false;
		deActivated.emit(1);
	}
	/********************
	 *  @Description Locks Talent after child has points
	 ********************/
	public void lock()
	{
		this.locked = true;
	}
	/********************
	 *  @Description Unlocks Talent after child is empty
	 ********************/
	public void unLock()
	{
		locked = false;
	}
	
	
	//Dependency Handling
	/***********************
	 * @Description This function adds the recognition that this talent leads to another upon maxing out
	 * Sets Dependency = true, adds the child Talent's coordinates to a list of children
	 ***********************/	
	public void addChild(int ctier, int cpos)
	{		
		hasDependency = true;
		QPair<Integer, Integer> q = new QPair<Integer, Integer>(ctier, cpos);
		child.add(q);
	}
	/************************
	 * @param ptier
	 * @param ppos
	 * @Description Adds recognition that this talent is the the child of some parent
	 * If this talent has a parent, the handler locks the parent if at least one point is spent in a child
	 ************************/
	public void setParent(int ptier, int ppos)
	{
		isDependent = true;
		parent = new QPair<Integer, Integer>(ptier, ppos);
	}
	
	public void drawChild(QPair<Integer, Integer> c, QPainter painter)
	{
		QRect arrow = new QRect();
		painter.setPen(QColor.darkGray);
		int toX = (c.second - position) * 60 - 40;
		int toY = (c.first - tier) * 70 - 40;
		
		//Calculate where the child is, draw a rectangle to it
		
		//If Talent is in same position but a different tier, draw vertical arrow
		if(position == c.second && tier !=  c.first)
		{
			arrow = new QRect(width/2-2, height, 6, toY);
		}
		
		//If item is on same tier but different position, draw horizontal arrow
		if(tier == c.first && position != c.second)
		{
			arrow = new QRect(width, height/2, toX, 5);
		}
		
		if(this.isMaxed())
			painter.fillRect(arrow, new QBrush(QColor.yellow));
		else 
			painter.fillRect(arrow, new QBrush(QColor.darkGray));
		painter.drawRect(arrow);
	}
	 /************************************* 
	 * 
	 * Mouse Handling
	 * 
	 * 
	 **************************************/
	
	/**********************************************
	 * Left Mouse button
	 * If the left mouse button is pressed, the Talent "ranks up".
	 * 
	 * Right Mouse button
	 * If the right mouse button is pressed, the Talent "ranks down".
	 **********************************************/
	public void mousePressEvent(QGraphicsSceneMouseEvent event) {
		
	    if (event.button() == Qt.MouseButton.LeftButton) {
	    	rankUp();	      
	    	event.accept();
	    }
	    if (event.button() == Qt.MouseButton.RightButton) {
	    	rankDown();	      
	    	event.accept(); 
	    }
	    this.scene().update();
	    
	    
	}
	@Override
	public void hoverEnterEvent(QGraphicsSceneHoverEvent event) {
		//rw.setVisible(true);
		this.setZValue(100);
		this.scene().update();
		String r = "Rank: " + String.valueOf(this.ranksAchieved) + "/" + String.valueOf(this.ranks);
		String c = new String();
		if(ranksAchieved == 0)
			c = rankInfo.get(ranksAchieved) + "\n";
		else if(ranksAchieved < ranks)
			c = "Current Rank: " + rankInfo.get(ranksAchieved-1) + "\nNext Rank: " + rankInfo.get(ranksAchieved) + "\n";
		else if(ranksAchieved == ranks)
			c = rankInfo.get(ranksAchieved-1) + "\n";
		
		this.setToolTip(name + "\t" + r + "\nPosition = x: " + String.valueOf(scenePos().x()) + " y:" + String.valueOf(scenePos().y()) + " z: " + String.valueOf(zValue()) + "\n" + c);
		hovering.emit(this);
		event.accept();
		
		// TODO Auto-generated method stub
		super.hoverEnterEvent(event);
	}
	@Override
	public void hoverLeaveEvent(QGraphicsSceneHoverEvent event) {
		//rw.setVisible(false);
		this.scene().update();
		this.setZValue(-100);
		super.hoverLeaveEvent(event);		
	}	


	public boolean rankUp()
	{
		if (!isMaxed() && active && !locked)
		{
			ranksAchieved++;
			if (isMaxed()) maxed.emit(1);
			pointSpent.emit(tier, position, 1);
			this.update();
			currentRank = rankInfo.get(ranksAchieved-1);
			return true;
		}
		return false;	
	}
	private boolean rankDown() 
	{
		if(ranksAchieved > 0 && !locked)
		{
			boolean wasMaxed = isMaxed();
			ranksAchieved--;
			if (wasMaxed) unMaxed.emit(1);
			pointSpent.emit(tier, position, -1);
			currentRank = rankInfo.get(ranksAchieved-1);
			return true;
		}
		return false;
	}
	public void undo()
	{
		ranksAchieved++;
		this.update();
	}
	public void undoRU()
	{
		ranksAchieved--;
		this.update();
	}
	boolean isMaxed()
	{
		return ranksAchieved == ranks;
	}
	boolean isEmpty()
	{
		if(ranksAchieved > 0) return false;
		else return true;
	}
	public void printStatus()
	{
		System.out.println("Rank: " + String.valueOf(this.ranksAchieved) + "/" + String.valueOf(this.ranks));
		System.out.print("Activated: " + String.valueOf(active));
		System.out.println(" Locked: " + String.valueOf(locked));
		System.out.println("Tier: " + String.valueOf(this.tier));
		System.out.println(String.valueOf("x: " + this.pos().x() + " y: " + this.pos().y()));
		
	}
	public String getName()
	{
		return name;
	}
	public int getTier()
	{
		return tier;
	}
	public int getPosition()
	{
		return position;
	}
	public int posXInt()
	{
		return (int)pos().x();
	}
	public int posYInt()
	{
		return (int)pos().y();
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	//Rank Window
	private class RankWindow extends QGraphicsItem
	{
		String name;
		public RankWindow(String n, Talent t, int pos)
		{
			setParentItem(t);
			name = n;			
		}
		
		private QRectF boundingRect = new QRectF(0, 0, 150, 80);
		public QRectF boundingRect()
		{
			return boundingRect;
		}
		
		/***************************************************** 
		 * Shape: This function is an interface function QT requires of QGraphicItems
		 * Shape defines the shape of the object; Used in collision detection
		 * Ours has a defined height and width
		 *****************************************************/
		QPainterPath shape = new QPainterPath();
		{
			shape.addRoundRect(boundingRect, 20);
		}
		
		public QPainterPath shape() {
			return shape;
		}
		
		/*****************************************************
		 * Paint: This function is an interface function QT requires of QGraphicItems
		 * Purpose: Draws the GraphicsItem on screen using a combination of Brushes, Pens and Pixmaps. 
		 *****************************************************/
		public void paint(QPainter painter, QStyleOptionGraphicsItem option,
		QWidget widget)
		{
	
			//Brush & Light Blue color for BG		
			QBrush brush = new QBrush(QColor.black);			
			if (!scene().collidingItems(this).isEmpty())
			{
				//brush.setColor(QColor.red);
			}			
			/****************************************************
			 * Drawing the Child Connection
			 * If the talent has a child, it draws an arrow from itself to the child
			 * This is done by subtracting the talent's tier from the child's tier # then multiplying that by the height.
			 * The child is always in the same x-position
			 * S
			 *****************************************************/
			
			painter.fillPath(shape, brush);
			painter.drawPath(shape);		

			// Draw the Icon associated with this talent	
			painter.setPen(QColor.darkGray);
			//Draw the Box that borders the ranks/ranksAchieved
			QRectF box = boundingRect;		
			QPainterPath pp = new QPainterPath();		
			pp.addRoundRect(box, 25);
			painter.fillPath(pp, brush);
			painter.drawPath(pp);
			
			//Draw the rankAchieved/ranks
			painter.drawText(0, 0, 100, 15, 0, name);	
			painter.drawText(0, 20, 100, 15, 0, String.valueOf(zValue()));	
			QTextOption o = new QTextOption();
			o.setWrapMode(QTextOption.WrapMode.WordWrap);
			
			for(int i = 0; i < rankInfo.size(); i++)
			{
				painter.drawText(new QRectF(0, 15+i*15, 150, 15), rankInfo.get(i), o);
			}
			
		}
	}
}
